스프링이 어떻게 성격이 비슷한 여러 종류의 기수을 추상화하고 이를 일관된 방법으로 사용할 수 있도록 지원하는지 알아본다.

지금의 UserDao는 어떠한 비즈니스 로직도 갖고 있지 않기 때문에 간단한 비즈니스 로직을 추가해보자.
UserDao를 다수의 회원이 가입할 수 있는 인터넷 서비스의 사용자 관리 모듈에 적용한다고 생각해보고, 단지 정보를 넣고 검색하는 것 외에 정기적으로 사용자의 활동내역을 참고해서 레벨을 조정해주는 기능을 넣어보자.

필드 추가

Level을 이늄 타입으로 정의해 사용한다. 주의할 점은, Level 이늄은 오브젝트이므로 DB에 저장할 때에는 정수형 값으로 알맞게 변환해줘야 한다. 그러므로 LevelintValue() 메소드를 만들어 사용한다. 또한 반대로 가져올 때에는 int로 level 정보를 가져온다. 이때는 Level의 스태틱 메소드인 valueOf()를 이용해 int타입의 값을 Level 타입의 이늄 오브젝트로 만들어서 setLevel()메소드에 넣어 준다.

사용자 수정 기능 추가

update()기능을 사용할 때, 테스트로는 검증하지 못하는 오류가 있을 수 있다. 바로 UPDATE 문장에서 WHERE절을 빼먹는 경우다. 수정하지 않아야 할 로우의 내용이 그대로 남아 있는지를 확인하지 못하는 문제가 있다.

첫번째 해결 방법은 update()가 돌려주는 리턴 값을 확인해본다. JdbcTemplateupdate()UPDATEDELETE 같이 테이블의 내용에 영향을 주는 SQL을 실행하면 영향받은 로우의 개수를 돌려준다.

두번째 방법은 테스트를 보강해서 원하는 사용자 외의 정보는 변경되지 않았음을 직접 확인하는 것이다.

UserService.upgradeLevels()

UserService.add()

사용자 관리 비즈니스 로직에서 대부분 구현했지만 아직 하나가 남았다. 처음 가입하는 사용자는 기본적으로 BASIC 레벨이어야 한다는 부분이다. 이를 어디다 담는 것이 좋을까?

  1. UserDaoJdbcadd()메소드
  2. User클래스에서 아예 level 필드를 Level.BASIC으로 초기화
  3. UserService에 로직을 넣는다.

1번은 주어진 DAO책임에만 관심을 가져야지, 비즈니스적인 의미를 지닌 정보를 설정하는 책임을 지는 것은 바람직하지 않다. 2번은 처음 가입할 때를 제외하면 무의미한 정보인데, 단지 이 로직을 담기 위해 클래스에서 직접 초기화하는 것은 좀 문제가 있어 보인다. 3번이 사용자가 등록될 때 적용할 만한 비즈니스 로직을 담당하면 적합할 것 같다.

코드 개선

upgradeLevels() 메소드 코드의 문제점

=> 성격이 다른 여러 가지 로직이 한데 섞여있다.

upgradeLevels() 리팩토링

기존의 upgradeLevels()메소드는 자주 변경될 가능성이 있는 구체적인 내용이 추상적인 로직의 흐름과 함께 섞여 있다. 이를 다음과 같이 변경해보자.

 public void upgradeLevels() {
        List<User> users = userDao.getAll();
        for (User user : users) {
            if (canUpgradeLevel(user)) {

구체적인 내용은 모르겠지만, upgradeLevels()메소드가 어떤 작업을 하는지는 쉽게 이해할 수 있다.

또한 User에게 레벨 업그레이드 작업을 요청하고, UserLevel에게 다음 레벨이 무엇인지 알려달라고 요청하는 방식으로 upgradeLevel(User user)메소드를 만든다.

private void upgradeLevel(User user) {
        user.upgradeLevel();
        userDao.update(user);
    }

Issues

junit harmcet